from django.shortcuts import get_object_or_404
from django.views import generic
from django.utils.text import slugify

from .models import BlogArticle, Category, Tag
from .serializers import BlogListSerializer, BlogRetrieveSerializer
from .filters import BlogFilter

from django_filters.rest_framework import DjangoFilterBackend

from rest_framework import viewsets, mixins, status
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import AllowAny
from rest_framework.decorators import action
from rest_framework.serializers import DateField

import markdown
from markdown.extensions.toc import TocExtension
import re

# Create your views here.

class IndexView(generic.ListView):
    model = BlogArticle
    template_name = 'blog/index.html'
    context_object_name = 'latest_article_list'
    paginate_by = 10 #开启分页功能，每页10个
    
    def get_queryset(self):
        return BlogArticle.objects.all()


class BlogDetailView(generic.DetailView):
    model = BlogArticle
    template_name = 'blog/detail.html'
    context_object_name = 'blog_article'
    
    def get(self, request, *args, **kwargs):
        response = super(BlogDetailView, self).get(request, *args, **kwargs)
        self.object.increase_views()
        return response
    
    def get_object(self, queryset=None):
        # 覆写 get_object 方法的目的是因为需要对 post 的 body 值进行渲染
        post = super().get_object(queryset=None)
        md = markdown.Markdown(extensions=[
            'markdown.extensions.extra',
            'markdown.extensions.codehilite',
            # 记得在顶部引入 TocExtension 和 slugify
            TocExtension(slugify=slugify),
        ])
        post.body = md.convert(post.body)

        m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)
        post.toc = m.group(1) if m is not None else ''

        return post


class CategoryView(IndexView):
    def get_queryset(self):
        cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))
        return super(CategoryView, self).get_queryset().filter(category=cate)


class TagView(IndexView):
    def get_queryset(self):
        tags = get_object_or_404(Tag, pk=self.kwargs.get('pk'))
        return super(TagView, self).get_queryset().filter(tags=tags)

class ArchiveView(IndexView):
    def get_queryset(self):
        year = self.kwargs.get('year')
        month = self.kwargs.get('month')
        return super().get_queryset().filter(createTime__year=year, createTime__month=month)

class BlogViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    serializer_class = BlogListSerializer
    queryset = BlogArticle.objects.all()
    pagination_class = PageNumberPagination
    permission_classes = [AllowAny]
    
    filter_backends = [DjangoFilterBackend]
    filterset_class = BlogFilter
    
    serializer_class_table = {
      'list': BlogListSerializer,
      'retrieve': BlogRetrieveSerializer,
    }

    def get_serializer_class(self):
        return self.serializer_class_table.get(
            self.action, super().get_serializer_class()
        )
    
    @action(
        methods=["GET"], detail=False, url_path="archive/dates", url_name="archive-date"
    )
    def list_archive_dates(self, request, *args, **kwargs):
        dates = BlogArticle.objects.dates("createTime", "month", order="DESC")
        date_field = DateField()
        data = [date_field.to_representation(date) for date in dates]
        return Response(data=data, status=status.HTTP_200_OK)
